package com.atguigu.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.client.CartFeignClient;
import com.atguigu.client.ProductFeignClient;
import com.atguigu.constant.MqConst;
import com.atguigu.entity.OrderDetail;
import com.atguigu.entity.OrderInfo;
import com.atguigu.enums.OrderStatus;
import com.atguigu.enums.ProcessStatus;
import com.atguigu.executor.MyExecutor;
import com.atguigu.mapper.OrderDetailMapper;
import com.atguigu.mapper.OrderInfoMapper;
import com.atguigu.service.OrderDetailService;
import com.atguigu.service.OrderInfoService;
import com.atguigu.util.HttpClientUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.junit.Test;
import org.springframework.amqp.core.Correlation;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 订单表 订单表 服务实现类
 * </p>
 *
 * @author zhangqiang
 * @since 2021-09-07
 */
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {
@Autowired
private OrderDetailService orderDetailService;
@Autowired
private RedisTemplate redisTemplate;
@Autowired
    ProductFeignClient productFeignClient;
    @Autowired
    private CartFeignClient cartFeignClient;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Value("${cancel.order.delay}")
    private Integer cancelOrderDelay;


    @Override
    public String splitOrder(Long orderId, String wareHouseIdSkuIdMapJson) {
        OrderInfo originalOrder = getOrderInfo(orderId);
        //设置子订单信息
        List<Map> wareHouseIdSkuIdMapList = JSON.parseArray(wareHouseIdSkuIdMapJson, Map.class);
        List<Map> childOrderInfoMapList = new ArrayList<>();
        for (Map wareHouseIdSkuIdMap : wareHouseIdSkuIdMapList) {
            String wareHouseId = (String)wareHouseIdSkuIdMap.get("wareHouseId");
            List<String> skuIdList= (List<String>) wareHouseIdSkuIdMap.get("skuIdList");
            //子订单的基本信息
            OrderInfo childOrderInfo = new OrderInfo();
            //批量为同名属性赋值
            BeanUtils.copyProperties(originalOrder, childOrderInfo);
            //设置子订单仓库id
            childOrderInfo.setWareHouseId(wareHouseId);
            //设置子订单的父id为orderId
            childOrderInfo.setParentOrderId(orderId);
            childOrderInfo.setId(null);
            
            //设置子订单的详细信息
            List<OrderDetail> originalOrderDetailList = originalOrder.getOrderDetailList();
            //c.设置子订单详情信息
            List<OrderDetail> childOrderDetailList=new ArrayList<>();
            BigDecimal totalMoney = new BigDecimal(0);
            for (OrderDetail originalOrderDetail : originalOrderDetailList) {
                for (String skuId : skuIdList) {
                    if (originalOrderDetail.getSkuId()==Long.parseLong(skuId)){
                        childOrderDetailList.add(originalOrderDetail);
                        //设置子订单总金额
                        BigDecimal orderPrice = originalOrderDetail.getOrderPrice();
                        String skuNum = originalOrderDetail.getSkuNum();
                        totalMoney = totalMoney.add(orderPrice.multiply(new BigDecimal(skuNum)));
                    }
                }
            }
            //设置子订单基本信息的订单详情信息
            childOrderInfo.setOrderDetailList(childOrderDetailList);
            //设置子订单的总价
            childOrderInfo.setTotalMoney(totalMoney);
            //保存子订单
            saveOrderAndDetail(childOrderInfo);
            //把子订单转换为json字符串
            Map<String, Object> dataMap = assembleWareHouseData(childOrderInfo);
            childOrderInfoMapList.add(dataMap);
        }
        //e.修改原始订单状态
        updateOrderStatus(originalOrder,ProcessStatus.SPLIT);
        return JSON.toJSONString(childOrderInfoMapList);
    }

    @Override
    public void sendMsgToWarehouse(OrderInfo orderInfo) {
        //将订单修改为已通知仓库
        updateOrderStatus(orderInfo,ProcessStatus.NOTIFIED_WARE);
        //拼接传递消息参数json数据
        String jsonData=JSON.toJSONString(assembleWareHouseData(orderInfo));
        //发送消息给仓库系统
        rabbitTemplate.convertAndSend(MqConst.DECREASE_STOCK_EXCHANGE,MqConst.DECREASE_STOCK_ROUTE_KEY,jsonData);

    }

    @Override
    public void sendMsgToWareHouse(OrderInfo orderInfo) {
        //将订单修改为已通知仓库
        updateOrderStatus(orderInfo, ProcessStatus.NOTIFIED_WARE);
        //凭借传递消息JSON信息
        String jsonData=JSON.toJSONString(assembleWareHouseData(orderInfo));
        //发消息给仓库系统
        redisTemplate.convertAndSend(MqConst.DECREASE_STOCK_EXCHANGE, MqConst.DECREASE_STOCK_ROUTE_KEY);
    }

    private Map<String, Object> assembleWareHouseData(OrderInfo orderInfo) {
        //
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("consigneeTel", orderInfo.getConsigneeTel());
        dataMap.put("orderId",orderInfo.getId() );
        dataMap.put("consignee",orderInfo.getConsignee() );
        dataMap.put("orderComment",orderInfo.getOrderComment() );
        dataMap.put("orderBody",orderInfo.getTradeBody() );
        dataMap.put("deliverAddress",orderInfo.getDeliveryAddress());
        dataMap.put("paymentWay",2);

        dataMap.put("wareId",orderInfo.getWareHouseId());
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        //商品清单放入list集合内
        ArrayList<Map> orderDetailMapList = new ArrayList<>();
        for (OrderDetail orderDetail : orderDetailList) {
            Map<String, Object> orderDetailMap = new HashMap<>();
            orderDetailMap.put("skuId",orderDetail.getSkuId());
            orderDetailMap.put("skuNum",orderDetail.getSkuNum());
            orderDetailMap.put("skuName",orderDetail.getSkuName());
            orderDetailMapList.add(orderDetailMap);
        }
        dataMap.put("datails",orderDetailList);
        String s = JSON.toJSONString(dataMap);
        return dataMap;
    }

    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        OrderInfo orderInfo = baseMapper.selectById(orderId);
        //拿取订单详情信息
        if (orderInfo!=null){
            QueryWrapper<OrderDetail> wrapper = new QueryWrapper<>();
            wrapper.eq("order_id", orderId);
            List<OrderDetail> list = orderDetailService.list(wrapper);
            orderInfo.setOrderDetailList(list);
        }
        return orderInfo;
    }



    @Override
    public void updateOrderStatus(OrderInfo orderInfo,ProcessStatus processStatus) {
        //修改订单状态
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        orderInfo.setProcessStatus(processStatus.name());
        baseMapper.updateById(orderInfo);
    }

    public Long saveOrderAndDetail(OrderInfo orderInfo){
        //保存订单信息
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        //商品对外订单号
        String outTradeNo="atguigu"+System.currentTimeMillis()+""+new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
        //订单主体信息
        orderInfo.setTradeBody("我的购物商品");
        orderInfo.setCreateTime(new Date());
        //设置订单支付过期时间,设置的是一天,默认一般30
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 1);
        orderInfo.setExpireTime(calendar.getTime());
        //订单进程状态
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        //商品总价格
        //        orderInfo.setTotalMoney(new BigDecimal(0.01));
        //保存订单详细信息
        baseMapper.insert(orderInfo);
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        for (OrderDetail orderDetail : orderDetailList) {
            orderDetail.setOrderId(orderInfo.getId());
        }
        orderDetailService.saveBatch(orderDetailList);
        rabbitTemplate.convertAndSend(
                MqConst.CANCEL_ORDER_EXCHANGE,
                MqConst.CANCEL_ORDER_ROUTE_KEY,
                orderInfo.getId(),
                correlationData->{
                    correlationData.getMessageProperties().setDelay(cancelOrderDelay);
                    return correlationData;
                });
        return orderInfo.getId();
    }



    @Override
    public void deleteTradeNo(String userId) {
        String tradeNoKey="user:"+userId+":tradeNo";
        redisTemplate.delete(tradeNoKey);
    }

    @Override
    public boolean checkTradeNo(String tradeNo, String userId) {
        String tradeNoKey="user:"+userId+":tradeNo";
        String redisTradeNo = (String)redisTemplate.opsForValue().get(tradeNoKey);
        return tradeNo.equals(redisTradeNo);
    }

    @Override
    public String generateTradeNo(String userId) {
        String tradeNo= UUID.randomUUID().toString();
        //把流水号放到redis中
        String tradeNoKey="user:"+userId+":tradeNo";
        redisTemplate.opsForValue().set(tradeNoKey,tradeNo);
        return tradeNo;
    }
    @Override
    public List<String> checkStockAndPrice(String userId, OrderInfo orderInfo) {
        //新建一个list用于保存警告信息
        List<String> warningInfoList = new ArrayList<>();
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        //异步编排的集合
        List<CompletableFuture> mulitFutureList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(orderDetailList)) {
            for (OrderDetail orderDetail : orderDetailList) {
                //看每个商品库存是否足够 调用接口
                //http://localhost:8100/hasStock?skuId=24&num=99
                Long skuId = orderDetail.getSkuId();
                String skuNum = orderDetail.getSkuNum();
                CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
                    String result = HttpClientUtil.doGet("http://localhost:8100/hasStock?skuId=" + skuId + "&num=" + skuNum);
                    //0:无库存   1:有库存
                    if ("0".equals(result)) {
                        warningInfoList.add(orderDetail.getSkuName() + "库存不足!");
                    }
                }, MyExecutor.getInstance());
                mulitFutureList.add(voidCompletableFuture);
                CompletableFuture<Void> voidCompletableFuture1 = CompletableFuture.runAsync(() -> {
                    BigDecimal realTimePrice = productFeignClient.getSkuPrice(skuId);
                    if (orderDetail.getOrderPrice().compareTo(realTimePrice) != 0) {
                        warningInfoList.add(orderDetail.getSkuName() + "价格有变化");
                        //更新缓存价格
                        cartFeignClient.queryFromDbToRedis(userId);
                    }
                }, MyExecutor.getInstance());
                mulitFutureList.add(voidCompletableFuture1);
            }
        }
        CompletableFuture[] completableFutures = new CompletableFuture[mulitFutureList.size()];
        CompletableFuture.allOf(mulitFutureList.toArray(completableFutures)).join();
        return warningInfoList;
    }

    //方式一
//@Override
//    public List<String>   checkStockAndPrice(String userId,OrderInfo orderInfo){
//        //集合保存警告信息
//        List<String> warningInfoList = new ArrayList<>();
//        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
//        if (!CollectionUtils.isEmpty(orderDetailList)){
//            //查看库存
//            for (OrderDetail orderDetail : orderDetailList) {
//                Long skuId = orderDetail.getSkuId();
//                String skuNum = orderDetail.getSkuNum();
//                String result = HttpClientUtil.doGet("http://localhost:9001/hasStock?skuId=" + skuId + "&num=" + skuNum);
//                if ("0".equals(result)){
//                    warningInfoList.add(orderDetail.getSkuName()+"库存不足!");
//                }
//                //验证价格是否为最新价格
//                BigDecimal realTimePrice = productFeignClient.getSkuPrice(skuId);
//                if (orderDetail.getOrderPrice().compareTo(realTimePrice)!=0){
//                    warningInfoList.add(orderDetail.getSkuName()+"价格有变化");
//                    //更新缓存价格
//                    cartFeignClient.queryFromDbToRedis(userId);
//                }
//            }
//        }
//        return warningInfoList;
//    }

}



















